import EventEmitter from "events";
import { BinanceTrader } from "../binance/BinanceTrader";
import { MergeData } from "./DataHandler";
import { robot } from "../common/DingRobot";
import { errLogger, outLogger } from "../common/logger";
import { TradingStrategy } from "./TradingStrategy";
import { autoToFixed } from "../utils";
import SymbolOrderConfigEntity from "../module/symbol-order-config/SymbolOrderConfig.entity";
import { AutoOrderConfig, AutoTradeType } from './types';
import dayjs from "dayjs";

// 虚拟交易机器人 现货余额，u本位余额，现货下单、合约下单
export class Trader {
  public tradingStrategy: TradingStrategy;
  public autoOrderList: SymbolOrderConfigEntity[] = [];
  private exchangeTraders: BinanceTrader[] = [];
  private eventEmitter = new EventEmitter();

  constructor() {
    this.init()
  }

  init() {
    this.tradingStrategy = new TradingStrategy();
  }
  updatePrice(type: AutoTradeType, symbol: string, price: number) {
    for (const trader of this.exchangeTraders) {
      if (type === 'futures') {
        trader.updateFuturesPrice(symbol, price);
      } else if (type === 'delivery') {
        trader.updateDeliveryPrice(symbol, price);
      }
    }
  }
  updateUserSDK(userid: number, config: Parameters<BinanceTrader['updateSDK']>[0]) {
    const userTrader = this.findUserTrader(userid);
    if (userTrader) {
      userTrader.updateSDK(config);
    }
  }
  async watchOrderRisk(userid: number, symbol: string, tradeType: AutoTradeType) {
    const userTrader = this.findUserTrader(userid);
    if (userTrader) {
      if (tradeType === 'futures') {
        const positions = await userTrader.getFuturesPositions(symbol);
        userTrader.riskModel.updatePositions(positions, 'futures');
      } else if (tradeType === 'delivery') {
        const positions = await userTrader.getDeliverysPositions(symbol);
        userTrader.riskModel.updatePositions(positions, 'delivery');
      }
   
    }
  }
  async beforeOrder(strategy_id: number, { symbol, close: price }: MergeData, action: "BUY" | "SELL") {
    outLogger.info(`strategy_id: ${strategy_id} beforeOrder ${symbol}(${price}) ${action}`);
    for (const orderConfig of this.autoOrderList) {
      const { trade_type, buy_usdt, sell_usdt, enabled, strategy, userid } = orderConfig;
      if (strategy.id !== strategy_id || !enabled || symbol != orderConfig.symbol) {
        continue;
      }
      outLogger.info(`beforeOrder  userid: ${userid}`);
      const userTrader = this.findUserTrader(userid);

      if (userTrader) {
        const dateStr = dayjs(new Date()).utcOffset(8).format("MM/DD HH:mm:ss");
        robot.markdown(
          `信号通知`,
          `${action === 'BUY' ? '<font color=#5EBF7E>BUY</font>' : '<font color=#F6465D>SELL</font>'} -> ${symbol}(${price}) \n ${dateStr}  \n by ${userTrader.getInfo().username}`
        );
      }
      if (trade_type === 'spot') {
        userTrader.beforeSpotOrder(symbol, action, orderConfig)
      } else if (trade_type === 'futures') {
        userTrader.beforeFuturesOrder(symbol, action, orderConfig).catch((err) => {
          outLogger.error(err.message)
        });
      } else if (trade_type === 'delivery') {
        userTrader.beforeDeliveryOrder(symbol, action, orderConfig);
      } 
    }
  }
  // async closeAllOrder(userid: number, symbol: string, tradeType: AutoTradeType) {
  //   const userTrader = this.findUserTrader(userid);
  //   if (tradeType === 'futures') {
  //     userTrader.closeAllFuturesOrder(symbol);
  //   } else if (tradeType === 'delivery') {
  //     userTrader.closeAllDeliveryOrder(symbol);
  //   }
  // }

  /**
   * 删除所有 symbol 的交易，管理员用
   * @param symbol 
   */
  removeSymbol(symbol: string) {
    this.tradingStrategy.removeSymbol(symbol);
  }

  addUserOrder(config: SymbolOrderConfigEntity) {
    const old = this.autoOrderList.find(item => item.id === config.id);
    if (!config.strategy) {
      errLogger.error('没有配置策略', config);
      return
    }
    const userTrader = this.findUserTrader(config.userid);
    if (old == null) {
      this.autoOrderList.push(config);
      this.addSymbolStrategy(config.strategy.id, config.symbol, config.strategy.strategy);
      userTrader.updateRiskModelConfig(config.symbol, config.config);
    } else {
      this.updateUserOrder(config);
    }
    
  }
  updateUserOrder(config: SymbolOrderConfigEntity) {

    for (let i = 0; i < this.autoOrderList.length; i++) {
      const orderConfig = this.autoOrderList[i];
      if (orderConfig.id === config.id) {
        const userTrader = this.findUserTrader(config.userid);
        if (!userTrader) {
          throw Error('未设置交易所账号')
        }
        if (!orderConfig.strategy) {
          errLogger.error('没有配置策略', config);
        }
        Object.assign(orderConfig, config);
        this.udpateCustomStrategy(orderConfig.strategy.id, orderConfig.symbol, orderConfig.strategy.strategy);
        userTrader.updateRiskModelConfig(orderConfig.symbol, orderConfig.config);
        return;
      }
    }
  }
  /** 添加用户自定义策略 */
  addSymbolStrategy(strategy_id: number, symbol: string, code: string) {
    outLogger.info(`addUserSymbolStrategy ${symbol} strategy_id: ${strategy_id} `);
    this.tradingStrategy
    .addCustomStrategy(String(strategy_id), symbol, {code})
    .onSignal((signal, kline) => {
      this.beforeOrder(strategy_id, kline, signal);
    });
  }
  udpateCustomStrategy(strategy_id: number, symbol: string, options) {
    this.tradingStrategy.udpateCustomStrategy(String(strategy_id), symbol, options)
  }
  removeUserSymbolStrategy(userid: number, symbol: string) {
    const userTrader = this.findUserTrader(userid);
    if (userTrader) {
      this.tradingStrategy.removeCustomStrategy({id: String(userid), symbol});
      userTrader.riskModel.updatePositions([], 'futures');
      userTrader.riskModel.updatePositions([], 'delivery');
    }
  }
  
  addExchangeTrader(newExchangeTrader: BinanceTrader) {
    const userid = newExchangeTrader.getUserId();
    let has = false;
    for (let i = 0; i < this.exchangeTraders.length; i++) {
      const userTrader = this.exchangeTraders[i];
      if (userTrader.getUserId() === userid) {
        has = true;
      }
    }
    outLogger.info('addExchangeTrader: len ', this.exchangeTraders.length)
    if (!has) {
      this.exchangeTraders.push(newExchangeTrader);
      return true
    }
    return false
  }

  /**
   * 删除用户所有策略和交易
   * @param userid 
   */
  removeUserTrader(userid: number) {
    for (let i = 0; i < this.exchangeTraders.length; i++) {
      const userTrader = this.exchangeTraders[i];
      if (userTrader.getUserId() === userid) {
        this.exchangeTraders[i].destroy();
        this.exchangeTraders.splice(i, 1);
        this.tradingStrategy.removeCustomStrategy({id: String(userid)});
      }
    }
  }

  findUserTrader(userid: number) {
    for (let i = 0; i < this.exchangeTraders.length; i++) {
      const userTrader = this.exchangeTraders[i];
      if (userTrader.getUserId() == userid) {
        return userTrader;
      }
    }
    return null;
  }
  /**
   * 删除用户的交易订单
   * @param userid 
   * @param symbol 
   */
  removeUserSymbol(userid: number, symbol: string) {
    this.removeUserSymbolStrategy(userid, symbol);
  }

  addData(data: MergeData,  period: "15m" | "4h" | "1d") {
    this.tradingStrategy.push(data, period);
  }
  updateData(data: MergeData,  period: "15m" | "4h" | "1d") {
    this.tradingStrategy.update(data, period);
  }
  destroy () {
    this.eventEmitter.removeAllListeners();
    this.tradingStrategy.destroy();
    this.exchangeTraders = undefined;
  }
}